package com.apes.fn.server.productRequireManage.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.apes.fn.server.productRequire.ProductRequire;
import com.apes.fn.server.productRequire.ProductRequireRepository;
import com.apes.scm.masterdata.enumeration.model.BusinessParam;
import com.apes.scm.masterdata.enumeration.repository.BusinessParamRepository;
import com.apes.fn.scm.contract.FnContract;
import com.apes.fn.scm.contract.FnContractRepository;
import com.apes.fn.server.productRequireManage.model.ReplenishmentBusinessImpAbstract;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.jpa.spec.model.Filter;
import com.apes.framework.jpa.spec.model.Group;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.rop.converter.DateUtils;
import com.apes.framework.util.DateUtil;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.ReflectUtil;
import com.apes.scm.account.tax.model.Tax;
import com.apes.scm.account.tax.service.TaxService;
import com.apes.scm.contract.model.Contract;
import com.apes.scm.contract.repository.ContractRepository;
import com.apes.scm.masterdata.frame.model.Dept;
import com.apes.scm.masterdata.frame.repository.DeptRepository;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.masterdata.party.repository.PartyRoleRepository;
import com.apes.scm.masterdata.party.service.SupplierService;
import com.apes.scm.masterdata.product.model.ProductUom;
import com.apes.scm.masterdata.product.repository.ProductRepository;
import com.apes.scm.masterdata.product.repository.ProductUomRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;

@Service("replePurSumItemService")
public class ReplePurSumItemService extends ReplenishmentBusinessImpAbstract {

    @Autowired
    private RequirePurchasePriceService requirePurchasePriceService;
    @Autowired
    private ContractRepository contractRepository;
    @Autowired
    private BusinessParamRepository businessParamRepository;
    @Autowired
    private ProductUomRepository productUomRepository;
    @Autowired
    private FnContractRepository fnContractRepository;
    @Autowired
    private TaxService taxService;
    @Autowired
    private PartyRoleRepository partyRoleRepository;
    @Autowired
    private DeptRepository deptRepository;
    @Autowired
    private ProductRepository productRepository;
    @Autowired
    private SupplierService supplierService;

    @Override
    public JSONObject sumRequireItem(JSONObject getJO) {
        JSONArray newRequireItems = new JSONArray();
        JSONArray requireItemErrorLog = new JSONArray(); // 记录要货日志
        boolean isCheck = false; // 是否勾选
        int noPrice = 0; // 1:无价格, 2:选择价格和最新报价不一致
        Map<String, ProductRequire> requireCache = new HashMap<>(); // 缓存要货单，避免重复查询
        JSONArray productRequireItems = getJO.getJSONArray("productRequireItems");
        for (int i = 0, iLen = productRequireItems.size(); i < iLen; i++) {
            JSONObject item = productRequireItems.getJSONObject(i);
            String productRequireId = item.getString("productRequireId");
            if (requireCache.get(productRequireId) == null) {
                requireCache.put(productRequireId, getBean(ProductRequireRepository.class).findOne(productRequireId));
            }
            if (requireCache.get(productRequireId).getVersion() != item.getInteger("version")) throw new RuntimeException("单据已变动, 请重新查询, 要货单号: " + productRequireId);

            if (!item.getBooleanValue("selectFlag")) continue;

            // 获取价格
            Set<Map> newPriceItem = requirePurchasePriceService.replinishPurchasePriceSumm(item);
            if (newPriceItem.isEmpty()) {
                noPrice = 1;
                continue;
            }

            // 获取合同
            List supplierIds = this.obtainPriceSupplier(newPriceItem);
            List<Contract> contracts = this.obtainContract(new JSONObject(MapUtil.mapper("locationId", item.getJSONObject("location").getString("id"),
                    "locationCompanyId", item.getJSONObject("locationCompany").getString("id"),
                    "contractIdAndNameOrPartnerIdAndName", supplierIds, "type", "replenishment")));

            // 拼接要货采购所需要的额外数据
            JSONObject newPurchaseRequireItemObj = this.appendRequireItemNeedDataSingle(item, newPriceItem, contracts);


            // 查看是否与最新报价价格相同
            boolean lastPriceSame = requirePurchasePriceService.baturuPriceChangeJudge(newPriceItem, item);
            if (!lastPriceSame) {
                noPrice = 2;

                // 组装日志
                requireItemErrorLog.add(
                        MapUtil.mapper("id", item.getString("id"), "errorMessage", "巴图鲁价格有变动，需重新询价",
                                "operate", "生成供应商订单")
                );
            } else {
                newPurchaseRequireItemObj.put("priceConsistent", true); // 价格一致标记，生成供应商判断用
            }

            isCheck = true;
            newRequireItems.add(newPurchaseRequireItemObj);

        }
        if (noPrice == 1) throw new RuntimeException("无商品有价格文件!");
        if (!isCheck) throw new RuntimeException("请先勾选数据!");

        return new JSONObject(MapUtil.mapper("item", newRequireItems, "requireItemErrorLog", requireItemErrorLog));
    }

    // 采购弹出框 - 拼接要货采购所需要的额外数据
    private JSONObject appendRequireItemNeedDataSingle(JSONObject item, Set<Map> newPriceItem, List<Contract> contracts) {
        String productId = item.getJSONObject("product").getString("id");
        String platformId = item.getJSONObject("platform").getString("id");
        String inquiryId = item.getString("commodityInquiryOrderId");
        String uniqueValue = item.getString("uniqueValue");

        JSONObject returnData = new JSONObject();
        for (int i = 0, iLen = contracts.size(); i < iLen; i++) { // 采购 - 弹第一框时，只获取一条数据即可
            Contract contract = contracts.get(i);
            returnData.clear();
            returnData.putAll(this.appendNewPurchaseRequireItem(item));
            for (Map m : newPriceItem) {
                JSONObject priceObj = new JSONObject(m);
                String priceSupplierId = priceObj.getString("SUPPLIER_ID");
                String priceProductId = priceObj.getString("PRODUCT_ID");
                String priceXJDH = priceObj.getString("XJDH");
                String priceUniqueValue = priceObj.getString("uniqueValue");
                if (this.judgeAppendPurRequirItemFillCondi(inquiryId, priceXJDH, platformId, priceSupplierId, priceProductId, productId, contract, uniqueValue, priceUniqueValue)) {
                    returnData.putAll(this.appendNewPurchaseRequireItemPrice(contract, priceObj, returnData));
                    return returnData;
                }
            }
        }
        return returnData;
    }

    // 采购弹出框 - 拼接要货采购所需要的额外数据
    private JSONArray appendRequireItemNeedData(JSONObject item, Set<Map> newPriceItem, List<Contract> contracts) {
        String productId = item.getJSONObject("product").getString("id");
        String platformId = item.getJSONObject("platform").getString("id");
        String inquiryId = item.getString("commodityInquiryOrderId");
        String uniqueValue = item.getString("uniqueValue");

        Set<JSONObject> data = new HashSet<>();
        contracts.forEach(contract -> {
            newPriceItem.stream().collect(Collectors.groupingBy(price -> {
                return !StringUtils.isEmpty(price.get("XJDH"));
            })).forEach((k, v) -> {
                v.stream().forEach(price -> {
                    JSONObject priceObj = new JSONObject(price);
                    String priceSupplierId = priceObj.getString("SUPPLIER_ID");
                    String priceProductId = priceObj.getString("PRODUCT_ID");
                    String priceXJDH = priceObj.getString("XJDH");
                    String priceUniqueValue = priceObj.getString("uniqueValue");
                    boolean meetCondiPrice = false;
                    if (k) {
                        meetCondiPrice = this.judgeAppendPurRequirItemFillCondi(inquiryId, priceXJDH, platformId, priceSupplierId, priceProductId, productId, contract, uniqueValue, priceUniqueValue);
                    } else {
                        meetCondiPrice = this.judgeAppendPurRequirItemFillCondi(priceSupplierId, priceProductId, productId, contract);
                    }
                    if (meetCondiPrice) {
                        JSONObject newReturnPurchaseData = this.appendNewPurchaseRequireItem(item);
                        newReturnPurchaseData.putAll(this.appendNewPurchaseRequireItemPrice(contract, priceObj, item));
                        data.add(newReturnPurchaseData);
                    }
                });
            });
        });

        JSONArray returnData = new JSONArray();
        returnData.addAll(data);
        return returnData;
    }

    // 采购弹出框 - 价格和合同匹配是否满足条件
    private boolean judgeAppendPurRequirItemFillCondi(String inquiryId, String priceXJDH, String xjdzxbPT, String priceSupplierId, String priceProductId, String productId, Contract contract, String requireUniqueValue, String priceUniqueValue) {
        List<BusinessParam> businessParamList = businessParamRepository.findAllByQueryKey("NoTaxPlatform");
        List noTaxPlatformId = businessParamList.stream().map(BusinessParam::getValue).collect(Collectors.toList());

        // 询价- 无税平台 + 供应商（协议） | 含税平台 + 供应商（非协议）
        // 非询价 【价格商品 + 明细商品匹配】 + 【价格供应商 + 合同供应商】
        boolean isInquiryTax = StringUtils.hasText(inquiryId) && noTaxPlatformId.contains(xjdzxbPT) && contract.getContractType().getId().equals("Contract.contractType.platform") && inquiryId.equals(priceXJDH);
        boolean isInquiryNoTax = StringUtils.hasText(inquiryId) && !noTaxPlatformId.contains(xjdzxbPT) && contract.getContractType().getId().equals("Contract.contractType.supplier") && inquiryId.equals(priceXJDH);
        boolean noInquiry = StringUtils.isEmpty(inquiryId) && StringUtils.isEmpty(requireUniqueValue);
        boolean UniqueValueFlag = StringUtils.isEmpty(requireUniqueValue)?false:StringUtils.isEmpty(priceUniqueValue)?false:requireUniqueValue.equals(priceUniqueValue)?true:false;
        boolean otherPrice = contract.getPartner().getId().equals(priceSupplierId) && priceProductId.equals(productId);


        return (isInquiryTax || isInquiryNoTax || noInquiry || UniqueValueFlag) && otherPrice;
    }

    // 采购弹出框 - 价格和合同匹配是否满足条件
    private boolean judgeAppendPurRequirItemFillCondi(String priceSupplierId, String priceProductId, String productId, Contract contract) {
        return contract.getPartner().getId().equals(priceSupplierId) && priceProductId.equals(productId);
    }


    // 采购 - 供应商 - 获取所有价格
    public Page<Map> obtainAllPrice(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        JSONObject currentData = getJO.getJSONObject("conditionModel").getJSONObject("node");
        String companyId = currentData.getJSONObject("locationCompany").getString("id");

        // 获取价格
        Set<Map> newPriceItem = requirePurchasePriceService.replinishPurchasePriceSumm(currentData);
        if (newPriceItem.isEmpty()) throw new RuntimeException("未找到价格, 请检查采购价格文件、询价单价格是否过期！");

        // 获取合同
        List supplierIds = this.obtainPriceSupplier(newPriceItem);
        List<Contract> contracts = this.obtainContract(currentData.getJSONObject("location").getString("id"), companyId, supplierIds);

        JSONArray includePriceItem = appendRequireItemNeedData(currentData, newPriceItem, contracts);
        Pageable pageable = PageRequest.of(getJO.getIntValue("page"), getJO.getIntValue("size"));
        PageImpl page = new PageImpl<>(includePriceItem, pageable, includePriceItem.size());
        return page;
    }



    private JSONObject appendNewPurchaseRequireItemPrice(Contract contract, JSONObject priceObj, JSONObject item) {
        double P001 = priceObj.getDoubleValue("P001");
        String xjbj = priceObj.getString("XJBJ");
        String productId = item.getJSONObject("product").getString("id");
        String locationCompanyId = item.getJSONObject("locationCompany").getString("id");
        String platformId = item.getJSONObject("platform").getString("id");

        double toBeReplenishedQty = item.getDoubleValue("toBeReplenishedQty");
        ProductUom minFactorUom = productUomRepository.findAll(JpaDsl.toCriteriaByEq("factor", 1, "uomCategory.id", productId)).get(0);
        ProductUom purchaseUom = productUomRepository.findBypurchaseUom(productId);

        JSONObject additionalData = new JSONObject();
        List fields = Arrays.asList("id", "name");

        PartyRole supplier = contract.getPartner();
        additionalData.put("contract", this.accordFieldValue(contract, fields));
        additionalData.put("cooperation", this.accordFieldValue(contract.getCooperation(), fields));
        additionalData.put("supplier", this.accordFieldValue(supplier, fields));
        additionalData.put("contractCompany", this.accordFieldValue(contract.getCompany(), fields));
        if (("1007".equals(platformId) && contract.getCompany().getId().equals("1007"))  || (!"1007".equals(platformId) && contract.getCompany().getId().equals("1007"))) {
            Dept dept = deptRepository.findAll(JpaDsl.toCriteriaByEq("company.id", locationCompanyId, "deptType.id", "000006")).get(0);
            additionalData.put("dept", this.accordFieldValue(dept, fields));
            additionalData.put("company", item.get("locationCompany"));
        } else {
            additionalData.put("dept", this.accordFieldValue(contract.getDept(), fields));
            additionalData.put("company", this.accordFieldValue(contract.getCompany(), fields));
        }
        String companyId = additionalData.getJSONObject("company").getString("id");
        Tax tax = taxService.getPurchaseTax(partyRoleRepository.findOne(companyId), partyRoleRepository.findOne(supplier.getId()), productRepository.findOne(productId));
        additionalData.put("tax", this.accordFieldValue(tax, Arrays.asList("id", "name")));

        double calcuP001 = this.accordPlatformObtainP001(contract.getCompany().getId(), P001, xjbj, minFactorUom, purchaseUom, companyId, supplier.getId(), productId);
        additionalData.put("priceSource", priceObj.get("priceSource"));
        additionalData.put("P001", calcuP001);
        additionalData.put("amount", toBeReplenishedQty * calcuP001);
        additionalData.put("priceCeiling", calcuP001);
        additionalData.put("bareValence", P001); // 裸价

        return additionalData;
    }



    // 采购弹出框 - 拼接满足条件数据返回
    private JSONObject appendNewPurchaseRequireItem(JSONObject item) {
        double toBeReplenishedQty = item.getDoubleValue("qtyRequire") - item.getDoubleValue("qtyAssigned") - item.getDoubleValue("qtyEnded") - item.getDoubleValue("orderQty");
        String productId = item.getJSONObject("product").getString("id");
        ProductUom purchaseUom = productUomRepository.findBypurchaseUom(productId);

        JSONObject additionalData = new JSONObject();
        List fields = Arrays.asList("id", "name");
        additionalData.put("checkData", item.getBooleanValue("checkData"));
        additionalData.put("location", item.getJSONObject("location"));
        additionalData.put("locationCompany", item.getJSONObject("locationCompany"));
        additionalData.put("productRequireId", item.getString("productRequireId"));
        additionalData.put("toBeReplenishedQty", toBeReplenishedQty);
        additionalData.put("distributionQty", toBeReplenishedQty);
        additionalData.put("product", item.getJSONObject("product"));
        additionalData.put("purchaseUom", this.accordFieldValue(purchaseUom, fields));
        additionalData.put("requireUom", item.getJSONObject("uom"));
        additionalData.put("supplier", item.getJSONObject("supplier"));
        additionalData.put("sourceStateId", item.getString("sourceStateId"));
        additionalData.put("sourceStateCode", item.getString("sourceStateCode"));
        additionalData.put("platform", item.getJSONObject("platform"));
        additionalData.put("source", item.get("source"));
        additionalData.put("commodityInquiryOrderId", item.get("commodityInquiryOrderId"));
        additionalData.put("id", item.getString("id"));
        additionalData.put("site", item.getJSONObject("site"));
        additionalData.put("expectedArrivalTime", item.getDouble("expectedArrivalTime"));
        additionalData.put("purchasingGroup", item.get("purchasingGroup"));
        additionalData.put("customerExpand", item.get("customerExpand"));
        additionalData.put("spId", item.get("spId")); // 商品ID
        additionalData.put("channelType", item.get("channelType")); // 渠道
        additionalData.put("offerId", item.get("offerId")); // 报价单ID
        additionalData.put("creatorName", item.get("creatorName"));
        additionalData.put("store", item.get("store"));
        additionalData.put("wantInvoice", item.get("wantInvoice"));
        additionalData.put("qtyRequire", item.get("qtyRequire"));
        additionalData.put("qtyAssigned", item.get("qtyAssigned"));
        additionalData.put("qtyEnded", item.get("qtyEnded"));
        additionalData.put("orderQty", item.get("orderQty"));
        additionalData.put("version", item.get("version"));
        additionalData.put("sourceBusinessType", item.get("sourceBusinessType"));
        return additionalData;
    }

    /**
     * 对要货是含税平台进行加价
     * @param platformId 从合同上取, 是协议就是无税, 采购会和门店人员沟通
     * @param P001
     * @param minUom
     * @param purchaseUom
     * @return
     */
    private double accordPlatformObtainP001(String platformId, double P001, String xjbj, ProductUom minUom, ProductUom purchaseUom, String companyId, String supplierId, String productId) {
        List<BusinessParam> businessParamList = businessParamRepository.findAllByQueryKey("NoTaxPlatform");
        BusinessParam NoTaxPlatform = businessParamList.stream().filter(businessP -> businessP.getValue().equals(platformId)).findFirst().orElse(null);

        double ticketPoint = supplierService.getSupplierTicketPoint(companyId, supplierId, productId);
        boolean companyWantInvoice = partyRoleRepository.findOne(companyId).getParty().getCorporate().isWantInvoice();
        if ((!"TRUE".equals(xjbj) && ObjectUtils.isEmpty(NoTaxPlatform)) || companyWantInvoice) {
            P001 = P001 * (1 + ticketPoint / 100);
        }

        return minUom.computePrice(P001, purchaseUom);
    }

    // 获取合同
    private List<Contract> obtainContract(String locationId, String companyId, List supplierId) {
        List<Contract> contracts = new ArrayList<>();
        String operation = "";
        try {
            operation = invoke("scm.transferProductService.accordLCompanyChangeOperation", MapUtil.mapper("id", locationId));
        } catch (Exception e) {
            throw new RuntimeException("请检查 "+ companyId + " 公司是否有赋能合同 、平台协议、采购合同");
        }

        List<FnContract> fnContractList = fnContractRepository.qryValidFnContract(companyId);
        if (fnContractList.isEmpty() && "001073".equals(operation)) throw new RuntimeException(companyId + "公司没有【赋能合同】！");

        if (!fnContractList.isEmpty()) { // 赋能
            String fnCompanyId = fnContractList.get(0).getCompany().getId();
            contracts.addAll(contractRepository.accordingSupplierQuery(Arrays.asList(fnCompanyId), "Contract.contractType.platform", supplierId));

            // 剔除有平台合同的供应商, 有协议优选选协议
            contracts.addAll(contractRepository.qryValidContract(Arrays.asList("1001"), "Contract.contractType.supplier", supplierId));
        }

        List<BusinessParam> businessParams = businessParamRepository.accordingToCompanyContract(Arrays.asList(companyId));
        if (!businessParams.isEmpty()) { // 子公司
            List businessCompanys = businessParams.stream().map(singleBusiness -> singleBusiness.getValue()).collect(Collectors.toList());
            contracts.addAll(contractRepository.accordingSupplierQuery(businessCompanys, "Contract.contractType.supplier", supplierId));
        } else { // 直营
            contracts.addAll(contractRepository.accordingSupplierQuery(Arrays.asList(companyId), "Contract.contractType.supplier", supplierId));
        }
        if (contracts.isEmpty()) throw new RuntimeException(companyId + "公司请检查是否有【平台协议合同、采购合同】！");
        return contracts;
    }

    private List obtainPriceSupplier(Set priceArray) {
        List supplierIds = new ArrayList();
        Set<String> supplierIdSet = (Set<String>) priceArray.stream().map(price -> {
            Map priceObj = (Map) price;
            if (Double.valueOf(priceObj.get("P001").toString()) > 0 && !"A00000".equals(priceObj.get("SUPPLIER_ID"))) {
                return priceObj.get("SUPPLIER_ID").toString();
            } else {
                return "";
            }
        }).collect(Collectors.toSet());
        supplierIdSet.add("占位");
        supplierIds.addAll(supplierIdSet);

        return supplierIds;
    }

    // 根据实体获取制定字段的值
    private Map accordFieldValue(Object obj, List<String> fieldList){
        Map map = new HashMap();
        if (ObjectUtils.isEmpty(obj)) return map;
        fieldList.forEach(filed -> {
            map.put(filed,  ReflectUtil.getFieldValue(obj, filed));
        });
        return map;
    }


    // 采购订单界面 - 采购合同调用
    public List<Contract> externalObtainContract(SimpleRequest request) {
        JSONObject getJO = request.getJO();
        List<Contract> contracts = this.obtainContract(getJO);
        return contracts;
    }

    public List<Contract> obtainContract(JSONObject condi) {
        // 仓储公司
        String locationCompanyId = condi.getString("locationCompanyId");
        List<Contract> contracts = new ArrayList<>();
        PartyRole partyRole = partyRoleRepository.findOne(locationCompanyId);
        List<PartyRole> roles = partyRoleRepository.findAll(JpaDsl.toCriteriaByEq("party.id", partyRole.getParty().getId(), "role.id", "Warehousing"));
        if (!roles.isEmpty()) {
            List<Contract> platformContracts = this.findPlaformContract(locationCompanyId, JSONObject.parseObject(condi.toJSONString()));
            contracts.addAll(platformContracts);
            if (contracts.isEmpty()) throw new RuntimeException("未检查到有供应商签署平台协议！");
            return contracts;
        }

        // 获取运营模式
        String operation = "";
        try {
            operation = invoke("scm.transferProductService.accordLCompanyChangeOperation", MapUtil.mapper("id", condi.get("locationId")));
        } catch (Exception e) {
            throw new RuntimeException("请检查 "+ locationCompanyId + " 公司是否有赋能合同 、平台协议、采购合同");
        }
        if ("001073".equals(operation)) { // 赋能
            List<Contract> platformContracts = this.findPlaformContract(locationCompanyId, JSONObject.parseObject(condi.toJSONString()));
            contracts.addAll(platformContracts);

            // 查询合同，剔除有平台合同的供应商, 有协议优选选协议
            List<BusinessParam> businessParams = businessParamRepository.findAllByQueryKey("accordingToCompanyContract");
            List<Contract> purchaseContracts = this.findContract(businessParams, JSONObject.parseObject(condi.toJSONString()));
            if (platformContracts.isEmpty()) {
                contracts.addAll(purchaseContracts);
            } else {
                purchaseContracts.stream().forEach(contract -> {
                    platformContracts.forEach(platformContract -> {
                        if (!contract.getPartner().getId().equals(platformContract.getPartner().getId())) {
                            contracts.add(contract);
                        }
                    });
                });
            }
            if (contracts.isEmpty()) {
                throw new RuntimeException("未检查到有供应商签署采购合同、平台协议！公司：" + locationCompanyId);
            }
        } else { // 直营、子公司直接找合同
            List<BusinessParam> businessParams = businessParamRepository.findAllByQueryKey("accordingToCompanyContract");
            contracts.addAll(this.findContract(businessParams, JSONObject.parseObject(condi.toJSONString())));
            if (contracts.isEmpty()) {
                throw new RuntimeException("未检查到有供应商签署采购合同！公司：" + locationCompanyId);
            }
        }
        return contracts;
    }

    // 获取协议公用部分
    private List<Contract> findPlaformContract(String locationCompanyId, JSONObject copyCondi) {
        // 获取赋能合同
        List<FnContract> fnContractList = fnContractRepository.qryValidFnContract(locationCompanyId);
        if (fnContractList.isEmpty()) throw new RuntimeException(locationCompanyId + "公司没有【赋能合同】！");

        // 存入条件
        copyCondi.put("contractTypeId", "Contract.contractType.platform");
        copyCondi.put("contractCompanyId", fnContractList.stream().map(fncontract -> {return fncontract.getCompany().getId();}).collect(Collectors.toList()));

        // 查询协议
        List<Contract> platformContracts = contractRepository.findAll(this.accordingFindContract(copyCondi));
        return platformContracts;
    }

    // 查找合同公用部分
    private List<Contract> findContract(List<BusinessParam> businessParams, JSONObject condi) {
        JSONObject copyCondi = JSONObject.parseObject(condi.toJSONString());
        copyCondi.put("contractTypeId", "Contract.contractType.supplier");
        copyCondi.put("contractCompanyId", businessParams.stream().map(businessParam -> {return businessParam.getValue();}).collect(Collectors.toSet()));
        return contractRepository.findAll(this.accordingFindContract(copyCondi));
    }


    // 这样拼接条件是为了 obtainContract 逻辑公用
    private List<Filter> publicCondi(String contractTypeId, String type, String sceneId) {
        List<Filter> filters = new ArrayList<>();
        Filter filter = new Filter();
        filter.setField("contractType.id");
        filter.setOperator("EQ");
        filter.setValue(contractTypeId);
        filters.add(filter);

        // 状态
        filter = new Filter();
        filter.setField("state");
        filter.setOperator("in");
        filter.setValue(Arrays.asList("approve", "extension"));
        filters.add(filter);

        // 有效期
        filter = new Filter();
        filter.setField("validFrom");
        filter.setOperator("LTE");
        filter.setValue(DateUtil.dateToDate(new Date(), DateUtils.SHOW_DATETIME_FORMAT));
        filters.add(filter);

        filter = new Filter();
        filter.setField("validPeriod");
        filter.setOperator("GTE");
        filter.setValue(DateUtil.dateToDate(new Date(), DateUtils.SHOW_DATETIME_FORMAT));
        filters.add(filter);

        // 剔除内部供应商
        filter = new Filter();
        filter.setField("partner.id");
        filter.setOperator("NIN");
        filter.setValue(this.innserSupplierIds(type, sceneId));
        filters.add(filter);
        return filters;
    }

    // 获取内部供应商
    private List<String> innserSupplierIds(String type, String sceneId) {
        List<String> innerSuppliers = partyRoleRepository.findAllInnerSupplier().stream().map(partyRole -> {return partyRole.getId();}).collect(Collectors.toList());
        if ("handPurchaseOrder".equals(type)) {
            if ("PO001".equals(sceneId)) {
                innerSuppliers.add("A00000");
                innerSuppliers.add("004465");
            }
        } else if ("replenishment".equals(type)) {
            innerSuppliers.add("A00000");
            innerSuppliers.add("004465");
        }
        return innerSuppliers;
    }

    /**
     * 赋能 - 获取协议
     * handPurchaseOrder - 手工采购订单
     * replenishment - 要货补货管理
     * @param condi
     * @return
     */
    private Specification accordingFindContract(JSONObject condi) {
        Group allCondi = new Group();
        List<Filter> filters = this.publicCondi(condi.getString("contractTypeId"), condi.getString("type"), condi.getString("sceneId"));

        // 公司
        Filter filter = new Filter();
        filter.setField("company.id");
        filter.setOperator("in");
        filter.setValue(condi.getJSONArray("contractCompanyId"));
        filters.add(filter);


        if ("replenishment".equals(condi.get("type"))) {
            filter = new Filter();
            filter.setField("partner.id");
            filter.setOperator("in");
            filter.setValue(condi.getJSONArray("contractIdAndNameOrPartnerIdAndName").toJavaList(Object.class));
            filters.add(filter);
            allCondi.setFilters(filters);
            return allCondi.build(false);

        } else if ("handPurchaseOrder".equals(condi.get("type"))) { // 手工采购获取合同
            filter = new Filter();
            if ("PO002".equals(condi.get("sceneId"))) { // 期初采购
                filter.setField("partner.id");
                filter.setOperator("in");
                filter.setValue(Arrays.asList("A00000"));
                filters.add(filter);
                allCondi.setFilters(filters);
                return allCondi.build(false);
            } else if ("PO003".equals(condi.get("sceneId"))) { // 现金采购
                filter.setField("partner.id");
                filter.setOperator("in");
                filter.setValue(Arrays.asList("004465"));
                filters.add(filter);
                allCondi.setFilters(filters);
                return allCondi.build(false);
            } else {
                allCondi.setFilters(filters); // 设置 setFilters
            }

            // 合同编码、合同名称、供应商编码、供应商名称 模糊查询, contractIdAndNameOrPartnerIdAndName 表示查询所有供应商合同或协议
            String contractIdAndNameOrPartnerIdAndName = condi.getString("contractIdAndNameOrPartnerIdAndName");
            if (StringUtils.hasText(contractIdAndNameOrPartnerIdAndName)) {
                List<Group> groups = new ArrayList<>();
                List<Filter> filters2 = new ArrayList<>();
                Group g1 = new Group();
                filter = new Filter();
                filter.setField("id");
                filter.setOperator("LIKE");
                filter.setValue(contractIdAndNameOrPartnerIdAndName);
                filters2.add(filter);

                filter = new Filter();
                filter.setField("name");
                filter.setOperator("LIKE");
                filter.setValue(contractIdAndNameOrPartnerIdAndName);
                filters2.add(filter);

                // 标准采购
                if ("PO001".equals(condi.get("sceneId"))) {
                    filter = new Filter();
                    filter.setField("partner.id");
                    filter.setOperator("LIKE");
                    filter.setValue(contractIdAndNameOrPartnerIdAndName);
                    filters2.add(filter);

                    filter = new Filter();
                    filter.setField("partner.party.name");
                    filter.setOperator("LIKE");
                    filter.setValue(contractIdAndNameOrPartnerIdAndName);
                    filters2.add(filter);
                }

                g1.setOperator("or");
                g1.setFilters(filters2);
                groups.add(g1);
                allCondi.setGroups(groups);
            }
        }
        return allCondi.build(false);
    }



}
